package com.xiguthings.waka.web.controller.wechat.wx;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xiguthings.waka.publicUtils.PropertiesUtil;
import com.xiguthings.waka.publicUtils.StringUtils;
import com.xiguthings.waka.web.controller.wechat.wx.tmpltMsg.TltMsg;
import org.apache.log4j.Logger;

import javax.net.ssl.HttpsURLConnection;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

public class WxConnExec {
    // public static String APPID = "wxe71aafcf4341cfaf";
    // public static String APPSECRET = "5884484c163e617eb09ce6a1202e0f93";
    // public static String APPID = "wx751e56d6dc24d637";
    // public static String APPSECRET = "f09586c3e462164fb272c7259d3f4b77";
    public static String PAYKEY = "";
    private static String accessToken = null;
    private static String jsTicket = null;
    private static long tokenTime = 0l;
    private static long jsTkTime = 0l;
    // 素材类型
    public static String IMAGE = "image";
    public static String VIDEO = "video";
    public static String VOICE = "voice";
    public static String NEWS = "news";

    /**
     * 获取公众号appid
     *
     * @return
     */
    public static String getWechatAppid() {
        return PropertiesUtil.getInstance().getPro("config/wx.properties", "wechat.APPID");
    }

    /**
     * 获取公众号appsecret
     *
     * @return
     */
    public static String getWechatAppsecret() {
        return PropertiesUtil.getInstance().getPro("config/wx.properties", "wechat.APPSECRET");
    }

    /**
     * 获取小程序appid
     *
     * @return
     */
    public static String getXcxAppid() {
        return PropertiesUtil.getInstance().getPro("config/wx.properties", "xcx.appid");
    }

    /**
     * 获取小程序secret
     *
     * @return
     */
    public static String getXcxSecret() {
        return PropertiesUtil.getInstance().getPro("config/wx.properties", "xcx.secret");
    }

    public static JSONObject sendTempletMsg(TltMsg msg) {
        String url = "https://api.weixin.qq.com/cgi-bin/message/template/send";
        // System.out.println(msg.getJsonValu());
        return WxConnExec.exec(url, msg.getJsonValu(), true);
    }

    /**
     * 根据配置文件创建自定义菜单
     *
     * @return
     */
    public static JSONObject createMenu(String jsonMenu) {
        // Log.debug(WxConnExec.class.getName() + ":" + jsonMenu);
        String url = "https://api.weixin.qq.com/cgi-bin/menu/create";
        return WxConnExec.exec(url, jsonMenu, true);
    }

    /**
     * 获得当前微信菜单的定义
     *
     * @return
     */
    public static JSONObject getmenu() {
        String url = "https://api.weixin.qq.com/cgi-bin/menu/get";
        return WxConnExec.exec(url, null, true);
    }

    /**
     * 换取网页授权access_token
     *
     * @param refresh_token
     * @return
     */
    public static JSONObject refresh_fans_token(String refresh_token) {

        String url = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=#APPID#&grant_type=refresh_token&refresh_token=#REFRESH_TOKEN#";
        url = url.replace("#REFRESH_TOKEN#", refresh_token).replace("#APPID#", getWechatAppid());
        return WxConnExec.exec(url, null, false);
    }

    /**
     * 通过code换取网页授权access_token
     *
     * @param code
     * @return
     */
    public static JSONObject getAccess_tokenByCode(String code) {
        // https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
        String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=#APPID#&secret=#SECRET#&code=#CODE#&grant_type=authorization_code";
        url = url.replace("#APPID#", WxConnExec.getWechatAppid()).replace("#SECRET#", WxConnExec.getWechatAppsecret())
                .replace("#CODE#", code);
        return WxConnExec.exec(url, null, false);
    }

    /**
     * 删除微信菜单
     */
    public static void delMenu() {
        String url = "https://api.weixin.qq.com/cgi-bin/menu/delete";
        WxConnExec.exec(url, null, true);
    }

    /**
     * 获得所有用户组
     *
     * @return
     */
    public static JSONObject getAllGroup() {
        String url = "https://api.weixin.qq.com/cgi-bin/groups/get";
        return WxConnExec.exec(url, null, true);
    }

    /**
     * 获取关注用户列表
     *
     * @return
     */
    public static JSONObject getUerList(String nextOpenId) {
        String url = "https://api.weixin.qq.com/cgi-bin/user/get";
        if (nextOpenId != null) {
            url += "?next_openid=" + nextOpenId;
        }
        return WxConnExec.exec(url, null, true);
    }

    /**
     * 根据openid获取已经关注用户的nike
     *
     * @param openid
     * @return
     */
    public static JSONObject getUserInfo(String openid) {
        String url = "https://api.weixin.qq.com/cgi-bin/user/info?openid=" + openid + "&lang=zh_CN";
        return WxConnExec.exec(url, null, true);
    }

    /**
     * 根据openid和access_token(网页授权的，和基础支持的不一样)拉取用户信息
     *
     * @param openid
     * @param access_web_token
     * @return
     */
    public static JSONObject getUserInfo(String openid, String access_web_token) {
        String url = " https://api.weixin.qq.com/sns/userinfo?access_token=" + accessToken + "N&openid=" + openid
                + "&lang=zh_CN";
        return WxConnExec.exec(url, null, false, false);
    }

    /**
     * 获取服务器上的素材列表
     *
     * @param type
     * @return
     */
    public static JSONObject getMaterial(String type) {
        String jsonParam = "{ \"type\":\"" + type + "\",\"offset\":0,\"count\":20}";
        String url = "https://api.weixin.qq.com/cgi-bin/material/batchget_material";
        return WxConnExec.exec(url, jsonParam, true);
    }

    /**
     * 向用户或管理员主动发送客服消息
     *
     * @param msg 发送消息内容的json字符串，将openid封装到了msg中
     * @return
     */
    public static JSONObject sendMsg(String msg) {
        String url = "https://api.weixin.qq.com/cgi-bin/message/custom/send";
        return WxConnExec.exec(url, msg, true);
    }

    /**
     * 获得JS的ticket 有效期是7200S，即2个小时,近两个小时时，重新获取ticket
     *
     * @return
     */
    public static String getJsapiTicket() {
        if ((System.currentTimeMillis() - jsTkTime) / 1000 <= 7100)
            return jsTicket;
        String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi";
        jsTicket = WxConnExec.exec(url, null, true).getString("ticket");
        jsTkTime = System.currentTimeMillis();
        return jsTicket;
    }


    /**
     * 根据小程序的loginCode，获取到openid
     *
     * @param loginCode
     * @return
     * @throws Exception
     */
    public static String xcxGetOpenid(String loginCode) throws Exception {
        if (StringUtils.isBlank(loginCode)) {
            return null;
        }

        String url = "https://api.weixin.qq.com/sns/jscode2session?" +
                "appid=" + getXcxAppid() + "&secret=" + getXcxSecret() + "&grant_type=authorization_code&js_code=" + loginCode;
        JSONObject jobj = WxConnExec.exec(url, null, false);// {"session_key":"dBhG610a2YkdNXkLwVFn9Q==","openid":"oDzTx5JngKXgTlaxndxoWWYqkkSY"}
        String openid = jobj.getString("openid");
        return openid;
    }

    /**
     * 获取访问的access token
     * <p>
     * 有效期是7200S，即2个小时,近两个小时时，重新获取ticket
     *
     * @return
     */
    private static void getAccessToken() {
        Logger log = Logger.getLogger(WxConnExec.class);
        if ((System.currentTimeMillis() - tokenTime) / 1000 <= 7100)
            return;

        String url = "https://api.weixin.qq.com/cgi-bin/token?" + "grant_type=client_credential&" + "appid="
                + getWechatAppid() + "&secret=" + getWechatAppsecret();
        try {
            HttpsURLConnection https = (HttpsURLConnection) new URL(url).openConnection();
            https.getDoInput();
            InputStream in = https.getInputStream();
            byte[] b = new byte[1024 * 4];
            int len = 0;
            String resStr = "";
            while ((len = in.read(b)) != -1) {
                resStr += new String(b, 0, len);
            }
            JSONObject json = JSON.parseObject(resStr);
            in.close();
            log.info("获取access_token:" + json.toString());
            if (json.containsKey("access_token")) {
                accessToken = json.getString("access_token");
                tokenTime = System.currentTimeMillis();
            } else {
                log.info("获得accessToken失败，请检查系统");
            }
            tokenTime = System.currentTimeMillis();
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 测试号
        // accessToken =
        // "9LGifxP5Y3Xv70ukptj4O0_Q1xk9zwTF0ZG8CB0dUcfIhnAcxZ3MHD7CfuK2x_D_5FOAt_Mbo1shIGGxAlKeX5KjhV3gSkbL1S9qHw7SPSaK5OxT5iHw9poxIQDYO1AxCSXdAIAXNS";
        // 正式号
        // accessToken =
        // "oFr7jvlpkeCnZZKdZftI8XxvsEQ7eMTNLp_xZeNp2jAom831u0lZ-U30rltmMQwkObbw6ycTllea0cp27TMS1KehMKJblcXPclisTTRInLx5GZl-gSKES2nSSWP52RGFPQIaABAZAS";
    }

    public static JSONObject exec(String action, String json, boolean needToken) {
        return exec(action, json, needToken, true);
    }

    /**
     * 连接微信服务器，执行命令
     *
     * @param actUrl：url
     * @param json：参数
     * @param needToken：是否需要token
     * @param needCylce：是事要循环执行
     * @return
     */
    private static JSONObject exec(String actUrl, String json, Boolean needToken, boolean needCylce) {
        Logger log = Logger.getLogger(WxConnExec.class);
        String rs = null;
        String surl = null;
        try {
            if (needToken) {
                getAccessToken(); // 检测更新accessToken
                surl = actUrl + (actUrl.indexOf("?") != -1 ? "&" : "?") + "access_token=" + accessToken;
            } else
                surl = actUrl;

            log.info("提交的url是：" + surl);
            log.info("发送的消息是：" + json);
            URL url = new URL(surl);

            HttpURLConnection http = (HttpURLConnection) url.openConnection();
            http.setRequestMethod("POST");
            http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            if (json != null)
                http.setDoOutput(true);
            http.setDoInput(true);
            System.setProperty("sun.net.client.defaultConnectTimeout", "30000");// 连接超时30秒
            System.setProperty("sun.net.client.defaultReadTimeout", "30000"); // 读取超时30秒
            http.connect();

            if (json != null) {
                OutputStream os = http.getOutputStream();
                os.write(json.getBytes("UTF-8"));// 传入参数
                os.flush();
                os.close();
            }
            InputStream is = http.getInputStream();
            int size = is.available();
            List<String> list = new ArrayList<String>();
            byte[] jsonBytes = new byte[size];
            int len = 0;
            while ((len = is.read(jsonBytes)) != -1) {
                String str = new String(jsonBytes, 0, len, "UTF-8");
                list.add(str);
                // System.out.println(str);
                // System.out.println(list.size());
                jsonBytes = new byte[size];
            }
            for (String str : list) {
                rs += str;
            }
            rs = rs.replace("null", "");
            System.out.println("请求返回结果:" + rs);
        } catch (Exception e) {
            e.printStackTrace();
            rs = "{'errcode':-1}";
        }

        // access_token过期，再次获取access_token，回调该法再次执行命令
        JSONObject jsonRS = JSON.parseObject(rs);
        // log.info("返回的消息是：" + jsonRS.toString());
        if (jsonRS.containsKey("errcode") && jsonRS.getInteger("errcode") == 40001) {
            tokenTime = 0L;
            if (needCylce == false) {
                return jsonRS;
            }
            return exec(actUrl, json, needToken, false);
        }
        return jsonRS;
    }

}